 // ------------------------------------------------------------------------------------------
// Licensed by Interprise Solutions.
// http://www.InterpriseSolutions.com
// For details on this license please visit  the product homepage at the URL above.
// THE ABOVE NOTICE MUST REMAIN INTACT.
// ------------------------------------------------------------------------------------------
using System;
using System.Data;
using System.Text.RegularExpressions;
using System.Collections;
using System.Data.SqlClient;
using InterpriseSuiteEcommerceCommon.Tool;
using System.Xml.Linq;

namespace InterpriseSuiteEcommerceCommon
{
    /// <summary>
    /// Summary description for Topic.
    /// this class is now changed in ML v5.7+ to NO LONGER do any automatic token replacement in the Topic object. The
    /// caller is now responsible for doing that after the topic object has been created, if they need to.
    /// </summary>
    public class Topic
    {
        private string m_TopicName = string.Empty;
        private string m_TopicID = string.Empty;
        private string m_LocaleSetting = string.Empty;
        private int m_SkinID = 1;
        private string m_Contents = string.Empty;
        private string m_ContentsRAW = string.Empty;
        private string m_SectionTitle = string.Empty;
        private string m_SETitle = string.Empty;
        private string m_SEKeywords = string.Empty;
        private string m_SEDescription = string.Empty;
        private string m_SENoScript = string.Empty;
        private string m_Password = string.Empty;
        private bool m_FromDB = false;
        private bool m_RequiresSubscription = false;
        private bool m_RequiresDisclaimer = false;
        private bool m_ShowOnWeb = true;
        private string m_FN = string.Empty;
        private string m_MasterLocale = string.Empty;
        private Regex m_CmdMatch = new Regex("\\(\\!(\\w+)(?:\\s(?:(\\w*)=(?:'|\")(.*?)(?:\"|'))?)*\\!\\)"); // Parses tokens of the form "(!command attribute="value" attribute2='value' ..!)"
        private MatchEvaluator m_CmdMatchEval;
        private Hashtable m_CommandHashtable;
        private string m_GraphicsColor = string.Empty;
        private string m_ContentsBGColor = string.Empty;
        private string m_PageBGColor = string.Empty;
        private Parser m_UseParser = null;

        public Topic(string TopicnName)
            : this(TopicnName, Customer.Current.LocaleSetting, 1, null)
        { }

        public Topic(string TopicName, int SkinID)
            : this(TopicName, Customer.Current.LocaleSetting, SkinID, null)
        { }

        public Topic(string TopicName, string LocaleSetting)
            : this(TopicName, LocaleSetting, 1, null)
        { }

        public Topic(string TopicName, string LocaleSetting, int SkinID)
            : this(TopicName, LocaleSetting, SkinID, null)
        { }

        public Topic(string TopicName, string LocaleSetting, int SkinID, Parser UseParser)
        {
            m_LocaleSetting = LocaleSetting;
            m_TopicID = GetTopicID(TopicName, LocaleSetting);
			m_SkinID = SkinID;
            m_TopicName = TopicName.Trim();
            m_CommandHashtable = new Hashtable();
            m_CmdMatchEval = new MatchEvaluator(CommandMatchEvaluator);
			m_UseParser = UseParser;
            LoadFromDB(m_TopicID);
		}

        /// <summary>
        /// Evaluates (!command value="xxx"!) tokens
        /// </summary>
        protected string CommandMatchEvaluator(Match match)
        {
            string cmd = match.Groups[1].Value.ToLowerInvariant();
            var parameters = new Hashtable();

			for (int i = 0; i < match.Groups[2].Captures.Count; i++)
			{
				string attr = match.Groups[2].Captures[i].Value;
				if (attr == null) 
				{
                    attr = string.Empty;
                }

                string val = match.Groups[3].Captures[i].Value;
                if (val == null)
                {
                    val = string.Empty;
                }
                try
                {
                    m_CommandHashtable.Add(cmd.ToLowerInvariant(), val);
                }
                catch { }
            }
            return string.Empty;
        }

        public string Contents
        {
            get
            {
                return m_Contents;
            }
        }

        public string GraphicsColor
        {
			get 
			{
				return m_GraphicsColor;
			}
		}

        public string ContentsBGColor
        {
            get
            {
                return m_ContentsBGColor;
            }
        }

        public string PageBGColor
        {
            get
            {
				return m_PageBGColor;
			}
		}

		public bool FromDB
		{
			get 
			{
				return m_FromDB;
			}
		}

        public Hashtable CommandHashtable
        {
            get
            {
                return m_CommandHashtable;
            }
        }

		public bool RequiresSubscription
		{
			get 
			{
				return m_RequiresSubscription;
			}
		}

		public bool RequiresDisclaimer
		{
			get 
			{
				return m_RequiresDisclaimer;
			}
		}

        public bool ShowOnWeb
        {
            get
            {
                return m_ShowOnWeb;
            }
        }

        public string TopicName
        {
            get
            {
                return m_TopicName;
            }
        }

        public string SectionTitle
        {
            get
            {
                return m_SectionTitle;
            }
        }

        public string Password
        {
            get
            {
                return m_Password;
            }
        }

        public string FN
        {
            get
            {
                return m_FN;
            }
        }

        public string TopicID
        {
            get
            {
                return m_TopicID;
            }
        }

        public int SkinID
        {
            get
            {
                return m_SkinID;
            }
        }

        public string SETitle
        {
            get
            {
                return m_SETitle;
            }
        }

        public string SEKeywords
        {
            get
            {
                return m_SEKeywords;
            }
        }

        public string SEDescription
		{
			get 
			{
				return m_SEDescription;
			}
		}

		        public string SENoScript
        {
            get
            {
                return m_SENoScript;
            }
        }
       
        // Find the specified topic content. note, we try to find content even if it doesn't exactly match the input specs, by doing an ordered lookup in various areas
		// we want to show SOME topic content if it is at all possible, even if the language is not right, etc...
		// Note: site id only used for file based topic _contents
		// Search Order is (yes, other orderings are possible, but this is the one we chose, where ANY db topic match overrides file content):
		// the other option would be to match on locales in the order of DB/File (Customer Locale), DB/File (Store Locale), DB/File (Null locale)
		// DB (customer locale)
		// DB (store locale)
		// DB (null locale)
		// File (customer locale)
		// File (store locale)
		// File (null locale)
		void LoadFromDB(string topicId)
        {
            m_FromDB = false;
            m_Contents = string.Empty;
            m_ContentsRAW = string.Empty;
            m_SectionTitle = string.Empty;
            m_RequiresSubscription = false;
            m_RequiresDisclaimer = false;
            m_Password = string.Empty;
            m_SETitle = m_TopicName;
            m_SEKeywords = string.Empty;
            m_SEDescription = string.Empty;
            m_SENoScript = string.Empty;
            m_FN = string.Empty;
            m_MasterLocale = m_LocaleSetting;
            m_TopicID = topicId;

            if (m_TopicID != string.Empty)
            {
                string sql = string.Format("SELECT * FROM EcommerceWebTopicView with (NOLOCK) WHERE TopicID = {0} AND LocaleSetting = {1} AND WebSiteCode = {2}",
                        DB.SQuote(m_TopicID), DB.SQuote(m_MasterLocale), DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode));

                using (var con = DB.NewSqlConnection())
                {
                    con.Open();
                    using (var reader = DB.GetRS(sql, con))
                    {
                        if (reader.Read())
                        {
                            m_FromDB = true;
                            m_TopicID = DB.RSField(reader, "TopicID");
                            m_TopicName = Convert.ToString(DB.RSField(reader, "Name")).Replace(" ", "-");
                            m_Contents = CommonLogic.ExtractBody(DB.RSField(reader, "TopicContent"), false);
                            m_Password = DB.RSField(reader, "Password");
                            m_RequiresSubscription = DB.RSFieldBool(reader, "RequiresSubscription");
                            m_RequiresDisclaimer = DB.RSFieldBool(reader, "RequiresDisclaimer");
                            m_GraphicsColor = DB.RSField(reader, "GraphicsColor");
                            m_ContentsBGColor = DB.RSField(reader, "ContentsBGColor");
                            m_PageBGColor = DB.RSField(reader, "PageBGColor");

                            if (m_Contents.Length != 0)
                            {
                                m_ContentsRAW = m_Contents;
                                m_SectionTitle = DB.RSField(reader, "Title");
                                m_SETitle = DB.RSField(reader, "SETitle");
                                m_SEKeywords = DB.RSField(reader, "SEKeywords");
                                m_SEDescription = DB.RSField(reader, "SEDescription");
                                m_SENoScript = DB.RSField(reader, "SENoScript");
                            }
                            else // nothing found, try master locale:
                            {
                                m_Contents = DB.RSField(reader, "TopicContent");
                                m_ContentsRAW = m_Contents;
                                m_SectionTitle = DB.RSField(reader, "Title");
                                m_SETitle = DB.RSField(reader, "SETitle");
                                m_SEKeywords = DB.RSField(reader, "SEKeywords");
                                m_SEDescription = DB.RSField(reader, "SEDescription");
                                m_SENoScript = DB.RSField(reader, "SENoScript");
                            }

                        }
                    }
                }
            }

			if(!m_FromDB) // did not find anything in db, try file based topic content (in skin dir as topicname.htm
			{
                m_FN = CommonLogic.SafeMapPath("skins/Skin_" + SkinID.ToString() + "/" + m_TopicName + "." + m_LocaleSetting + ".htm");
                if (!CommonLogic.FileExists(m_FN))
				{
					// try default store locale path:
                    m_FN = CommonLogic.SafeMapPath("skins/Skin_" + SkinID.ToString() + "/" + m_TopicName + "." + m_MasterLocale + ".htm");
                }
				if(!CommonLogic.FileExists(m_FN))
				{
					// try skin (NULL) path:
                    m_FN = CommonLogic.SafeMapPath("skins/Skin_" + SkinID.ToString() + "/" + m_TopicName + ".htm");
                }
                if (m_FN.Length != 0 && CommonLogic.FileExists(m_FN))
                {
                    m_Contents = CommonLogic.ReadFile(m_FN, true);
                    m_ContentsRAW = m_Contents;
                    m_SectionTitle = CommonLogic.ExtractToken(m_Contents, "<title>", "</title>");
                    m_Contents = CommonLogic.ExtractBody(m_Contents, false);
                    m_SETitle = CommonLogic.ExtractToken(m_Contents, "<PAGETITLE>", "</PAGETITLE>");
                    m_SEKeywords = CommonLogic.ExtractToken(m_Contents, "<PAGEKEYWORDS>", "</PAGEKEYWORDS>");
                    m_SEDescription = CommonLogic.ExtractToken(m_Contents, "<PAGEDESCRIPTION>", "</PAGEDESCRIPTION>");
                    m_SENoScript = CommonLogic.ExtractToken(m_Contents, "<PAGENOSCRIPT>", "</PAGENOSCRIPT>");
                }
                else
                {
                    //Topic does not exists.
                    m_ShowOnWeb = false;
                }
				if(m_CommandHashtable.Contains("contentsbgcolor"))
				{
					m_ContentsBGColor = m_CommandHashtable["contentsbgcolor"].ToString();
				}
				if(m_CommandHashtable.Contains("pagebgcolor"))
				{
					m_PageBGColor = m_CommandHashtable["pagebgcolor"].ToString();
				}
				if(m_CommandHashtable.Contains("graphicscolor"))
				{
					m_GraphicsColor = m_CommandHashtable["graphicscolor"].ToString();
				}
			}
			
			if(m_SETitle.Length == 0)
			{
				m_SETitle = m_SectionTitle;
			}
	
			if(AppLogic.ReplaceImageURLFromAssetMgr)
			{
				while(m_Contents.IndexOf("../images") != -1)
				{
					m_Contents = m_Contents.Replace("../images","images");
				}
			}
			if(m_UseParser != null)
			{
				m_Contents = m_UseParser.ReplaceTokens(m_Contents);
			}
			else
			{
				m_Contents = m_Contents.Replace("(!SKINID!)",SkinID.ToString());
			}

            if(Customer.Current.IsInEditingMode() && Security.IsAdminCurrentlyLoggedIn())
            {
                m_Contents = BuildCmsTemplate(topicId, m_Contents);
            }

        }

        private static string BuildCmsTemplate(string key, string value)
        {
            string html = String.Empty;
            var cachingInstance = CachingFactory.RequestCachingEngineInstance;

            if (!cachingInstance.Exist(DomainConstants.CMS_TOPIC_TEMPLATE))
            {
                var xml = new XElement(DomainConstants.XML_ROOT_NAME);
                xml.Add(new XElement(DomainConstants.XML_SECTION_TYPE, XMLSectionType.DISPLAY_CMS_TEMPLATE_FOR_TOPIC));

                var XmlPackage = new XmlPackage2("helper.page.default.xml.config", xml);

                html = XmlPackage.TransformString();
                cachingInstance.AddItem(DomainConstants.CMS_TOPIC_TEMPLATE, html);
            }
            else
            {
                html = cachingInstance.GetItem<string>(DomainConstants.CMS_TOPIC_TEMPLATE);
            }

            return html.Replace("(0)", key).Replace("(1)", value);
        }

        public static string GetName(string TopicID, string LocaleSetting)
        {
            var ds = DB.GetDS("select Name from Topic  with (NOLOCK) where Deleted=0 and TopicID=" + TopicID.ToString(), AppLogic.CachingOn, System.DateTime.Now.AddMinutes(AppLogic.CacheDurationMinutes()));
            string tmpS = string.Empty;
            if (ds.Tables[0].Rows.Count > 0)
            {
                tmpS = DB.RowFieldByLocale(ds.Tables[0].Rows[0], "Name", LocaleSetting);
            }
            ds.Dispose();
            return tmpS;
        }

        public static string GetTopicID(string TopicName, string LocaleSetting)
        {
            string tmp = string.Empty;

            // DELETED = 0 AND  (DELETED IS ALWAYS NULL in Interprise)
            using (var con = DB.NewSqlConnection())
            {
                con.Open();
                using (var rs = DB.GetRSFormat(con, string.Format("SELECT TopicID FROM EcommerceWebTopicView with (NOLOCK) WHERE Name = {0}  AND LocaleSetting= {1} AND WebSiteCode= {2}", 
                                                    DB.SQuote(TopicName.ToLower()),DB.SQuote(LocaleSetting), DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode))))
                {
                    if (rs.Read())
                    {
                        tmp = DB.RSField(rs, "TopicID");
                    }
                }
            }

            return tmp;
        }
    }
}



